home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / cmds / mklfs / mklfs.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-12-04  |  43.8 KB  |  1,421 lines

  1. /* 
  2.  * mklfs.c --
  3.  *
  4.  *    The mklfs program - Make a LFS file system on a disk.
  5.  *
  6.  * Copyright 1989 Regents of the University of California
  7.  * Permission to use, copy, modify, and distribute this
  8.  * software and its documentation for any purpose and without
  9.  * fee is hereby granted, provided that the above copyright
  10.  * notice appear in all copies.  The University of California
  11.  * makes no representations about the suitability of this
  12.  * software for any purpose.  It is provided "as is" without
  13.  * express or implied warranty.
  14.  */
  15.  
  16. #ifndef lint
  17. static char rcsid[] = "$Header: /sprite/src/admin/mklfs/RCS/mklfs.c,v 1.4 92/06/19 20:07:37 jhh Exp Locker: shirriff $ SPRITE (Berkeley)";
  18. #endif /* not lint */
  19.  
  20. #ifdef __STDC__
  21. /*
  22.  * If we are compiling on a machine that has a ASCII C compiler, set the
  23.  * define _HAS_PROTOTYPES which causes the Sprite header files to 
  24.  * expand function definitions to included prototypes.
  25.  */
  26. #define    _HAS_PROTOTYPES 
  27. #endif /* __STDC__ */
  28.  
  29. #include <sprite.h>
  30. #include <varargs.h>
  31. #include <stdio.h>
  32. #include <cfuncproto.h>
  33.  
  34. #include <option.h>
  35. #include <stddef.h>
  36. #include <stdlib.h>
  37. #include <time.h>
  38. #include <unistd.h>
  39. #include <string.h>
  40. #include <sys/file.h>
  41. #include <sys/types.h>
  42. #include <sys/stat.h>
  43. #include <sys/time.h>
  44. #include <bstring.h>
  45.  
  46. #include <fs.h>
  47. #include <kernel/fs.h>
  48. #include <kernel/dev.h>
  49. #include <kernel/fsdm.h>
  50. #include <kernel/fslcl.h>
  51. #include <kernel/devDiskLabel.h>
  52.  
  53. #include <kernel/lfsDesc.h>
  54. #include <kernel/lfsDescMap.h>
  55. #include <kernel/lfsFileLayout.h>
  56. #include <kernel/lfsSegLayout.h>
  57. #include <kernel/lfsStableMem.h>
  58. #include <kernel/lfsSuperBlock.h>
  59. #include <kernel/lfsUsageArray.h>
  60. #include <kernel/lfsStats.h>
  61.  
  62. #include "getMachineInfo.h"
  63.  
  64. /*
  65.  * Mklfs works by building parts of the file system in memory and
  66.  * then writing the parts to disk.  The following data structures
  67.  * describe the in memory format on a segment and checkpoint region.
  68.  */
  69.  
  70. /*
  71.  * SegMem - Description of a segment being initialized for a new file system.
  72.  */
  73. typedef struct SegMem {
  74.     char    *startPtr;       /* Start of segment memory. */
  75.     unsigned int diskAddress;      /* Disk address of start of segment. */
  76.     char    *dataPtr;      /* Next data block to be allocated. */
  77.     int        activeBytes;      /* Number of active bytes in segment. */
  78.     char    *summaryPtr;      /* Next summary bytes to be allocated. */
  79. } SegMem;
  80.  
  81. /*
  82.  * CheckPointMem - Desciption of checkpoint region being initialized for
  83.  *           a new file system. 
  84.  */
  85. typedef struct CheckPointMem {
  86.     char    *startPtr;    /* Start of checkpoint memory. */
  87.     char    *memPtr;     /* Next checkpoint byte to be allocated. */
  88. } CheckPointMem;
  89.  
  90. /*
  91.  * In memory version of a Lfs Stable Memory data structure.
  92.  */
  93.  
  94. typedef struct StableMem {
  95.     LfsStableMemParams *paramsPtr;
  96.     char        **blockPtrs;
  97. } StableMem;
  98.  
  99. /*
  100.  * Attributes of the root directory of the new file system.
  101.  */
  102. typedef struct RootDir {
  103.     int truncVersion;    /* Truncate version number of root directory. */
  104.     int    accessTime;    /* Time of last access of root directory. */
  105.     int    numBlocks;    /* Number of blocks in root direcotry. */
  106.     int descBlockAddress; /* Disk address of root directory block. */
  107. } RootDir;
  108.  
  109. static RootDir root;
  110.  
  111. /*
  112.  * DEFAULT_SEG_SIZE - Default size of an LFS segment in bytes.
  113.  */
  114. #define    DEFAULT_SEG_SIZE (DEV_BYTES_PER_SECTOR*1024)
  115.  
  116. int    blockSize = DEV_BYTES_PER_SECTOR; /* Minumin unit of allocation for
  117.                        * the file system.  Must be at
  118.                        * least a sector size. 
  119.                        */
  120. int    segmentSize = DEFAULT_SEG_SIZE;      /* Size of LFS segment in bytes. */
  121. int    numberSegments = -1;          /* Number of sections occupied by
  122.                        * by the file system. -1 means 
  123.                        * compute based on disk size. 
  124.                        */
  125. int    descBlockSize = FS_BLOCK_SIZE;      /* Size of the descriptor blocks. */
  126. int    maxDesc      = -1;              /* Maximum number of descriptors to
  127.                        * support.  -1 means compute based
  128.                        * on disk size. 
  129.                        */
  130. int    usageArrayBlockSize = FS_BLOCK_SIZE;   /* Block size of usage array
  131.                         * Data structure. */
  132. int    descMapBlockSize = FS_BLOCK_SIZE;    /* Block size of desc map
  133.                          * data structure. */
  134. int    segAlignment = DEV_BYTES_PER_SECTOR; /* Address multiple to 
  135.                           * start segments. */
  136. int    maxNumCacheBlocks = -1;        /* Maximum number of file cache
  137.                      * blocks on the machine 
  138.                      * being used. */
  139. int    maxCacheBlocksCleaned = -1;    /* Maximum number of file cache
  140.                      * blocks used during cleaning.
  141.                      */
  142. Boolean    verbose = FALSE;
  143. int    serverID = -1;    /* Server ID to put in file system. */
  144. char    *deviceName;    /* Device to write file system to. */
  145. double  maxUtilization = .85; /* Maximum utilization allowed for file system. */
  146. double  segFullLevel = .95;   /* Minumum utilization of a full segment. */
  147. int    checkpointInterval = 60; /* Checkpoint every 60 seconds. */
  148. char    *prefix = "test";
  149. #if 0
  150. char    *prefix = "(new domain)";    /* File system name (prefix). */
  151. #endif
  152.  
  153. Option optionArray[] = {
  154.     {OPT_DOC, (char *) NULL,  (char *) NULL,
  155. "This program generates an empty LFS file system. WARNING: This command\n will overwrite any existing data or file system on the specified device.\n Synopsis: \"mklfs [switches] deviceName [prefix]\"\n Command-line switches are:"},
  156.     {OPT_INT, "maxNumCacheBlocks", (Address) &maxNumCacheBlocks,
  157.         "Maximum number of cache blocks to avail on machine."},
  158.     {OPT_INT, "maxCacheBlocksCleaned", (Address) &maxCacheBlocksCleaned,
  159.         "Maximum number of cache blocks to clean at a time."},
  160.     {OPT_INT, "spriteID", (Address) &serverID,
  161.         "Sprite ID for superblock."},
  162.     {OPT_FLOAT, "maxUtilization", (Address) &maxUtilization,
  163.         "Maximum disk utilization allowed."},
  164.     {OPT_FLOAT, "segFullLevel", (Address) &segFullLevel,
  165.         "Minimum segment utilization for a full segment."},
  166.     {OPT_INT, "maxDesc", (Address) &maxDesc, 
  167.     "Maximum number of descriptors."},
  168.     {OPT_INT, "checkpointInterval", (Address) &checkpointInterval,
  169.     "Frequent of checkpoint in seconds."},
  170.     {OPT_INT, "blockSize", (Address) &blockSize, 
  171.     "Block size of file system in bytes."},
  172.     {OPT_INT, "segmentSize", (Address) &segmentSize, 
  173.     "Segment size of file system in bytes."},
  174.     {OPT_INT, "numSegments", (Address) &numberSegments, 
  175.     "Number of segment in file system."},
  176.     {OPT_INT, "segAlignment", (Address) &segAlignment,
  177.         "Insure that the first segment starts at this multiple."},
  178.     {OPT_INT, "descBlockSize", (Address) &descBlockSize, 
  179.     "Descriptor block size."},
  180.     {OPT_INT, "descMapBlockSize", (Address) &descMapBlockSize,
  181.         "Descriptor map block size"},
  182.     {OPT_INT, "usageArrayBlockSize", (Address) &usageArrayBlockSize,
  183.         "Segment usage array block size"},
  184.     {OPT_TRUE, "verbose", (Address)&verbose, "Print verbose information"}
  185. };
  186. /*
  187.  * Forward routine declartions. 
  188.  */
  189. extern void BuildInitialFileLayout _ARGS_((LfsFileLayoutParams *fileLayoutPtr,
  190.             SegMem *segPtr, CheckPointMem    *checkpointPtr));
  191. extern void BuildInitialDescMap _ARGS_((LfsDescMapParams *descParamsPtr, 
  192.             SegMem *segPtr, CheckPointMem    *checkpointPtr));
  193. extern void BuildInitialUsageArray _ARGS_((LfsSegUsageParams *usagePtr,
  194.             SegMem *segPtr, CheckPointMem    *checkpointPtr));
  195. static StableMem *BuildStableMem _ARGS_((int memType, int memBlockSize,
  196.             int entrySize, int maxNumEntries, 
  197.             LfsStableMemParams *smemParamsPtr));
  198. static void UpdateStableMem _ARGS_((StableMem *stableMemPtr, 
  199.             int entryNumber, char *entryPtr));
  200. static void LayoutStableMem _ARGS_((StableMem *stableMemPtr, 
  201.             SegMem *segPtr, CheckPointMem    *checkpointPtr));
  202.  
  203. static unsigned int GetDiskAddressOf _ARGS_((SegMem *segPtr));
  204. static void MakeRootDir _ARGS_((LfsFileDescriptor *rootDescPtr, 
  205.             LfsFileDescriptor *lostDescPtr,
  206.             SegMem *segPtr, RootDir *rootPtr));
  207. static void FileDescInit _ARGS_((LfsFileDescriptor *fileDescPtr, 
  208.             int fileNumber, int fileType));
  209. static void SetDescriptorMap _ARGS_((StableMem *stableMemPtr, 
  210.             int fileNumber, unsigned int diskAddress, 
  211.             int truncVersion, int accessTime));
  212. extern void WriteDisk _ARGS_((int diskFd, int blockOffset, char *bufferPtr, 
  213.             int bufferSize));
  214.  
  215. static Boolean IsPowerOfTwo _ARGS_((int ival));
  216. static Boolean IsMultipleOf _ARGS_((int imultiple, int ival));
  217. static int BlockCount _ARGS_((int objectSize, int blockSize));
  218. static void EraseOldFileSystem _ARGS_((int diskFd));
  219. static int ComputeDiskSize _ARGS_((int diskFd));
  220.  
  221. extern void panic();
  222. extern int  open _ARGS_((char *path, int flags, int mode));
  223.  
  224. /*
  225.  *----------------------------------------------------------------------
  226.  *
  227.  * main --
  228.  *
  229.  *    Main routine of mklfs - parse arguments and do the work.
  230.  *
  231.  * Results:
  232.  *    None.
  233.  *
  234.  * Side effects:
  235.  *    None.
  236.  *
  237.  *----------------------------------------------------------------------
  238.  */
  239.  
  240. int
  241. main(argc,argv)
  242.     int    argc;
  243.     char *argv[];
  244. {
  245.     int       diskFd, maxCheckPointSize, maxCheckPointBlocks, moduleType;
  246.     int        blocksPerSeg, segNum, startOffset;
  247.     LfsSuperBlock    *superBlockPtr;
  248.     char        *segMemPtr, *checkPointPtr, *summaryPtr;
  249.     SegMem    seg;
  250.     CheckPointMem checkpoint;
  251.     LfsSegSummaryHdr    *sumHdrPtr;
  252.     LfsCheckPointRegion *regionPtr;
  253.     LfsSegSummary     *segSumPtr;
  254.     LfsCheckPointHdr    *cpHdrPtr, *oldCheckPointPtr;
  255.     int        sizeInSectors;
  256.     extern ReturnStatus Proc_GetHostIDs 
  257.             _ARGS_((int *virtualHostPtr, int *physicalHostPtr));
  258.     int            partition;
  259.     struct timeval    tod;
  260.     struct stat        sbuf;
  261.  
  262.     GetMachineInfo(&serverID, &maxNumCacheBlocks);
  263.     /*
  264.      * Set the default number of file cache blocks to use while cleaning
  265.      * segments. We choose 8 megabytes or one third the number of cache
  266.      * blocks, which ever is less.
  267.      */
  268.  
  269.     if (maxCacheBlocksCleaned < 0) {
  270.     maxCacheBlocksCleaned = (8*1024*1024)/FS_BLOCK_SIZE;
  271.     if (maxCacheBlocksCleaned < maxNumCacheBlocks/3) {
  272.         maxCacheBlocksCleaned = maxNumCacheBlocks/3;
  273.     }
  274.     }
  275.  
  276.     argc = Opt_Parse(argc, argv, optionArray, Opt_Number(optionArray), 0);
  277.     if ((argc != 2) && (argc != 3)) { 
  278.          Opt_PrintUsage(argv[0], optionArray, Opt_Number(optionArray));
  279.      exit(1);
  280.     }
  281.     deviceName = argv[1];
  282.     if (argc == 3) {
  283.     prefix = argv[2];
  284.     if (strlen(prefix) >= 64) {
  285.         fprintf(stderr, "Length of prefix exceeds maximum (64)\n");
  286.         exit(1);
  287.     }
  288.     }
  289.     /*
  290.      * Validate the parameters.
  291.      */
  292.     if (!IsPowerOfTwo(blockSize) || (blockSize % DEV_BYTES_PER_SECTOR)) {
  293.     fprintf(stderr,"Blocksize (%d) not power of two or not multiple of sector size %d.\n",
  294.             blockSize, DEV_BYTES_PER_SECTOR);
  295.     exit(1);
  296.     }
  297.     if (!IsMultipleOf(segmentSize, blockSize)) {
  298.     fprintf(stderr,"Segment size (%d) is not a multiple of blockSize.\n",
  299.         segmentSize);
  300.     exit(1);
  301.     }
  302.     if (!IsMultipleOf(descBlockSize, blockSize)) {
  303.     fprintf(stderr,
  304.         "Descriptor block size (%d) is not a multiple of blockSize.\n",
  305.         descBlockSize);
  306.     exit(1);
  307.     }
  308.     if (!IsMultipleOf(descMapBlockSize, blockSize)) {
  309.     fprintf(stderr,
  310.         "Descriptor map block size (%d) is not a multiple of the blockSize.\n",
  311.         descMapBlockSize);
  312.     exit(1);
  313.     }
  314.     if (!IsMultipleOf(usageArrayBlockSize, blockSize)) {
  315.     fprintf(stderr,
  316.         "Usage array block size (%d) is not a multiple of the blockSize.\n",
  317.         usageArrayBlockSize);
  318.     exit(1);
  319.     }
  320.     if (!IsMultipleOf(segAlignment, DEV_BYTES_PER_SECTOR)) {
  321.     fprintf(stderr,
  322.         "segAlignment (%d) is not a multiple of the DEV_BYTES_PER_SECTOR.\n",
  323.         segAlignment);
  324.     exit(1);
  325.     }
  326.     segAlignment = segAlignment/DEV_BYTES_PER_SECTOR;
  327.  
  328.     if (maxCacheBlocksCleaned > maxNumCacheBlocks) {
  329.     fprintf(stderr, "maxCacheBlocksCleaned large than maxNumCacheBlocks\n");
  330.     exit(1);
  331.     } 
  332.  
  333.     /*
  334.      * Open of the device and write the file system.
  335.      */
  336.     diskFd = open(deviceName, O_RDWR, 0);
  337.     if (diskFd < 0) {
  338.     fprintf(stderr,"%s: ", argv[0]);
  339.     perror(deviceName);
  340.     exit(1);
  341.     }
  342.     sizeInSectors = ComputeDiskSize(diskFd);
  343.     if (numberSegments == -1) {
  344.     if (sizeInSectors < 0) {
  345.         fprintf(stderr,
  346.         "Can't compute disk size, must specified -numSegments\n");
  347.         exit(1);
  348.     }
  349.     /*
  350.      * Pack as many segments on to disk that will fit. Leave
  351.      * 128K at beginning for label, superblock, and checkpoint
  352.      * stuff.
  353.      */
  354.     numberSegments = (sizeInSectors*blockSize)/segmentSize - 
  355.                 ((128*1024)/segmentSize);
  356.     }
  357.     if (numberSegments < 0) {
  358.     fprintf(stderr,"Warning numberSegments (%d) < 0\n", numberSegments);
  359.     }
  360.  
  361.     if (maxDesc == -1) {
  362.     /*
  363.      * Unless otherwise told, generate one descriptor for
  364.      * every 8K of disk space.
  365.      */
  366.     maxDesc = (numberSegments * segmentSize) / 8192;
  367.     }
  368.  
  369.     /*
  370.      * Compute an upper bound of the checkpoint size. Checkpoint contains:
  371.      *        a checkpoint header.
  372.      *        as many as LFS_MAX_NUM_MODS check point regions.
  373.      *        a checkpoint trailer.
  374.      *        the desc map checkpoint info complete with block index.
  375.      *        the seg usage checkpoint info complete with block index.
  376.      *        some stats data.
  377.      */
  378.     maxCheckPointSize = sizeof(LfsCheckPointHdr) + 
  379.     sizeof(LfsCheckPointRegion) * LFS_MAX_NUM_MODS + 
  380.             sizeof(LfsCheckPointTrailer) +
  381.     sizeof(LfsDescMapCheckPoint) + sizeof(LfsStableMemCheckPoint) +
  382.     sizeof(int) * 
  383.         BlockCount(maxDesc*sizeof(LfsDescMapEntry),descMapBlockSize) +
  384.     sizeof(LfsSegUsageCheckPoint) +  sizeof(LfsStableMemCheckPoint) +
  385.         sizeof(int) * 
  386.         BlockCount(numberSegments*sizeof(LfsSegUsageEntry),usageArrayBlockSize)
  387.     + LFS_STATS_MAX_SIZE;
  388.  
  389.     /*
  390.      * Round to a multiple of the block size.
  391.      */
  392.     maxCheckPointBlocks = BlockCount(maxCheckPointSize,blockSize);
  393.     maxCheckPointSize = maxCheckPointBlocks * blockSize;
  394.     /*
  395.      * Fill in the super block header.
  396.      */
  397.     if (fstat(diskFd, &sbuf)) {
  398.     perror("Fstat of device failed");
  399.     exit(1);
  400.     }
  401.     partition = unix_minor(sbuf.st_rdev) & 7;
  402.     if (gettimeofday(&tod, NULL)) {
  403.     perror("gettimeofday failed");
  404.     exit(1);
  405.     }
  406.     startOffset = LFS_SUPER_BLOCK_OFFSET;
  407.     superBlockPtr = (LfsSuperBlock *) malloc(LFS_SUPER_BLOCK_SIZE);
  408.     bzero((char *)superBlockPtr, LFS_SUPER_BLOCK_SIZE);
  409.     superBlockPtr->hdr.magic = LFS_SUPER_BLOCK_MAGIC;
  410.     superBlockPtr->hdr.version = LFS_SUPER_BLOCK_VERSION;
  411.     superBlockPtr->hdr.blockSize = blockSize;
  412.     superBlockPtr->hdr.domainUID = tod.tv_sec;
  413.     superBlockPtr->hdr.partition = partition;
  414.     superBlockPtr->hdr.maxCheckPointBlocks = maxCheckPointBlocks;
  415.     superBlockPtr->hdr.checkpointInterval = checkpointInterval;
  416.     superBlockPtr->hdr.checkPointOffset[0] = startOffset + 
  417.             BlockCount(LFS_SUPER_BLOCK_SIZE, blockSize);
  418.     superBlockPtr->hdr.checkPointOffset[1]  = 
  419.     superBlockPtr->hdr.checkPointOffset[0] + maxCheckPointBlocks;
  420.     superBlockPtr->hdr.logStartOffset = 
  421.     superBlockPtr->hdr.checkPointOffset[1] +  maxCheckPointBlocks;
  422.     if ((superBlockPtr->hdr.logStartOffset % segAlignment) != 0) {
  423.     superBlockPtr->hdr.logStartOffset += 
  424.         (segAlignment - 
  425.             superBlockPtr->hdr.logStartOffset % segAlignment);
  426.     }
  427.     superBlockPtr->hdr.maxNumCacheBlocks = maxCacheBlocksCleaned;
  428.  
  429.     /*
  430.      * Reduce the number of segments until the file system fits on the disk.
  431.      */
  432.     if (sizeInSectors > 0) {
  433.     while ((superBlockPtr->hdr.logStartOffset + 
  434.         numberSegments * (segmentSize/blockSize)) *
  435.             blockSize/DEV_BYTES_PER_SECTOR >= sizeInSectors) {
  436.         numberSegments--;
  437.     }
  438.  
  439.     }
  440.     segMemPtr = calloc(1, segmentSize);
  441.  
  442.     summaryPtr = segMemPtr;
  443.  
  444.  
  445.     seg.startPtr = segMemPtr;
  446.     summaryPtr = segMemPtr + segmentSize - blockSize;
  447.     seg.dataPtr = summaryPtr;
  448.     seg.activeBytes = 0;
  449.     seg.diskAddress = superBlockPtr->hdr.logStartOffset;
  450.     seg.summaryPtr = summaryPtr + sizeof(LfsSegSummary) + 
  451.                 sizeof(LfsSegSummaryHdr);
  452.     checkPointPtr = calloc(1, maxCheckPointSize);
  453.     checkpoint.startPtr = checkPointPtr;
  454.     checkpoint.memPtr = checkPointPtr + sizeof(LfsCheckPointHdr) + 
  455.                      sizeof(LfsCheckPointRegion);
  456.     segSumPtr = (LfsSegSummary *) summaryPtr;
  457.     sumHdrPtr = (LfsSegSummaryHdr *) (summaryPtr + sizeof(LfsSegSummary));
  458.     regionPtr = (LfsCheckPointRegion *) 
  459.             (checkPointPtr + sizeof(LfsCheckPointHdr));
  460.     for (moduleType = LFS_FILE_LAYOUT_MOD; (moduleType < LFS_MAX_NUM_MODS);
  461.         moduleType++) { 
  462.     segMemPtr = seg.dataPtr;
  463.     if (moduleType == LFS_DESC_MAP_MOD) { 
  464.         BuildInitialDescMap(&superBlockPtr->descMap, &seg, &checkpoint);
  465.     } else if (moduleType == LFS_SEG_USAGE_MOD) {
  466.         BuildInitialUsageArray(&superBlockPtr->usageArray, &seg,
  467.                     &checkpoint);
  468.     } else if (moduleType == LFS_FILE_LAYOUT_MOD) {
  469.         BuildInitialFileLayout(&superBlockPtr->fileLayout, &seg, 
  470.                 &checkpoint);
  471.     } else {
  472.         panic("Unknown moduleType %d\n", moduleType);
  473.     }
  474.     sumHdrPtr->moduleType = moduleType;
  475.     sumHdrPtr->lengthInBytes = (seg.summaryPtr - (char *) sumHdrPtr); 
  476.     sumHdrPtr->numDataBlocks = (segMemPtr - seg.dataPtr)/blockSize;
  477.     sumHdrPtr = (LfsSegSummaryHdr *) seg.summaryPtr;
  478.     seg.summaryPtr += sizeof(LfsSegSummaryHdr);
  479.     regionPtr->type = moduleType;
  480.     regionPtr->size = (checkpoint.memPtr - (char *) regionPtr);
  481.  
  482.     regionPtr = (LfsCheckPointRegion *) checkpoint.memPtr;
  483.     checkpoint.memPtr += sizeof(LfsCheckPointRegion);
  484.     }
  485.     checkpoint.memPtr -= sizeof(LfsCheckPointRegion);
  486.     seg.summaryPtr -= sizeof(LfsSegSummaryHdr);
  487.  
  488.     ((LfsCheckPointTrailer *) checkpoint.memPtr)->timestamp = 1;
  489.     checkpoint.memPtr += sizeof(LfsCheckPointTrailer);
  490.     segSumPtr->magic = LFS_SEG_SUMMARY_MAGIC;
  491.     segSumPtr->timestamp = 1;
  492.     segSumPtr->prevSeg = 0;
  493.     segSumPtr->nextSeg = 1;
  494.     segSumPtr->size = (seg.summaryPtr - (char *) segSumPtr);
  495.     segSumPtr->nextSummaryBlock = -1;
  496.  
  497.     cpHdrPtr = (LfsCheckPointHdr *) checkpoint.startPtr;
  498.     cpHdrPtr->timestamp = 1;
  499.     cpHdrPtr->size = (checkpoint.memPtr - checkpoint.startPtr);
  500.     cpHdrPtr->version = 1;
  501.     cpHdrPtr->domainNumber = -1;
  502.     cpHdrPtr->attachSeconds = time(0);
  503.     cpHdrPtr->detachSeconds = time(0);
  504.     cpHdrPtr->serverID = serverID;
  505.     strncpy(cpHdrPtr->domainPrefix, prefix, 64);
  506.  
  507.     ((Lfs_StatsVersion1 *) checkpoint.memPtr)->size = sizeof(Lfs_StatsVersion1);
  508.     ((Lfs_StatsVersion1 *) checkpoint.memPtr)->version = 1;
  509.  
  510.     oldCheckPointPtr = (LfsCheckPointHdr *) calloc(1, blockSize);
  511.     oldCheckPointPtr->timestamp = 0;
  512.     oldCheckPointPtr->size = sizeof(LfsCheckPointHdr);
  513.     oldCheckPointPtr->version = 1;
  514.  
  515.     EraseOldFileSystem(diskFd);
  516.  
  517.     WriteDisk(diskFd, startOffset,(char *) superBlockPtr, LFS_SUPER_BLOCK_SIZE);
  518.     WriteDisk(diskFd, superBlockPtr->hdr.checkPointOffset[0],
  519.             checkPointPtr, maxCheckPointSize);
  520.     WriteDisk(diskFd, superBlockPtr->hdr.checkPointOffset[1], 
  521.             (char *) oldCheckPointPtr, sizeof(*oldCheckPointPtr));
  522.  
  523.     WriteDisk(diskFd, GetDiskAddressOf(&seg), seg.dataPtr, 
  524.             segmentSize - (seg.dataPtr - seg.startPtr));
  525.     bzero(segMemPtr, blockSize);
  526.     blocksPerSeg = segmentSize/blockSize;
  527.     if (verbose) {
  528.     printf("log start offset = %d\n", superBlockPtr->hdr.logStartOffset);
  529.     printf("numSegments = %d\n", numberSegments);
  530.     }
  531.     for (segNum = 1; segNum < numberSegments; segNum++) {
  532.     WriteDisk(diskFd, superBlockPtr->hdr.logStartOffset +
  533.         blocksPerSeg * segNum + (blocksPerSeg-1), segMemPtr, 
  534.         blockSize);
  535.     }
  536.  
  537.     if (verbose) {
  538.     printf("maxNumCacheBlocks = %d\n", maxNumCacheBlocks);
  539.     printf("maxCacheBlocksCleaned = %d\n", maxCacheBlocksCleaned);
  540.     printf("maxUtilization = %d\n", maxUtilization);
  541.     printf("maxDesc = %d\n", maxDesc);
  542.     printf("segAlignment = %d\n", segAlignment);
  543.     printf("blockSize = %d\n", blockSize);
  544.     printf("segmentSize = %d\n", segmentSize);
  545.     printf("numSegments = %d\n", numberSegments);
  546.     printf("descBlockSize = %d\n", descBlockSize);
  547.     printf("descMapBlockSize = %d\n", descMapBlockSize);
  548.     printf("usageArrayBlockSize = %d\n", usageArrayBlockSize);
  549.     printf("\n");
  550.     printf("minNumClean = %d\n", superBlockPtr->usageArray.minNumClean);
  551.     printf("minFreeBlocks = %d\n", superBlockPtr->usageArray.minFreeBlocks);
  552.     printf("wasteBlocks = %d\n", superBlockPtr->usageArray.wasteBlocks);
  553.     printf("numSegsToClean = %d\n", superBlockPtr->usageArray.numSegsToClean);
  554.     }
  555.  
  556.     exit(0);
  557.     return 0;
  558. }
  559.  
  560. /*
  561.  *----------------------------------------------------------------------
  562.  *
  563.  * BuildInitialFileLayout --
  564.  *
  565.  *    Build the file structure for the file system. This consists of
  566.  *    initializing the root directory
  567.  *
  568.  * Results:
  569.  *    None.
  570.  *
  571.  * Side effects:
  572.  *    Directory is added to the segments.
  573.  *
  574.  *----------------------------------------------------------------------
  575.  */
  576.  
  577. static void
  578. BuildInitialFileLayout(fileLayoutPtr, segPtr, checkpointPtr)
  579.     LfsFileLayoutParams    *fileLayoutPtr;    /* File system params in super block to
  580.                      * be filled in. */
  581.     SegMem        *segPtr;    /* Segment to add data blocks to. */
  582.     CheckPointMem    *checkpointPtr; /* Checkpoint info to be added. */
  583. {
  584.     LfsFileDescriptor    *descPtr;
  585.     LfsFileLayoutSummary *layoutSumPtr;
  586.     LfsFileLayoutDesc    *descLayoutPtr;
  587.  
  588.     /*
  589.      * Initialize the file layout parameters. 
  590.      */
  591.     fileLayoutPtr->descPerBlock = descBlockSize/sizeof(LfsFileDescriptor);
  592.     /*
  593.      * Allocate a descriptor block for the root directory's descriptor.
  594.      */
  595.     segPtr->dataPtr -= descBlockSize;
  596.     descPtr = (LfsFileDescriptor *) segPtr->dataPtr;
  597.  
  598.     segPtr->summaryPtr += sizeof(LfsFileLayoutDesc);
  599.     descLayoutPtr = (LfsFileLayoutDesc *) segPtr->summaryPtr;
  600.     descLayoutPtr->blockType = LFS_FILE_LAYOUT_DESC;
  601.     descLayoutPtr->numBlocks = descBlockSize/blockSize;
  602.     segPtr->activeBytes += 2*sizeof(LfsFileDescriptor);
  603.     root.descBlockAddress = GetDiskAddressOf(segPtr);
  604.  
  605.     MakeRootDir(descPtr+0, descPtr+1, segPtr, &root);
  606.     layoutSumPtr = (LfsFileLayoutSummary *) segPtr->summaryPtr;
  607.     segPtr->summaryPtr += sizeof(LfsFileLayoutSummary);
  608.     layoutSumPtr->blockType = LFS_FILE_LAYOUT_DATA;
  609.     layoutSumPtr->numBlocks = root.numBlocks;
  610.     layoutSumPtr->fileNumber = descPtr[0].fileNumber;
  611.     layoutSumPtr->truncVersion = root.truncVersion = 1;
  612.     layoutSumPtr->numDataBlocks = 1;
  613.     (*(int *) segPtr->summaryPtr) = 0;
  614.     segPtr->summaryPtr += sizeof(int);
  615.  
  616.     layoutSumPtr = (LfsFileLayoutSummary *) segPtr->summaryPtr;
  617.     segPtr->summaryPtr += sizeof(LfsFileLayoutSummary);
  618.     layoutSumPtr->blockType = LFS_FILE_LAYOUT_DATA;
  619.     layoutSumPtr->numBlocks = root.numBlocks;
  620.     layoutSumPtr->fileNumber = descPtr[1].fileNumber;
  621.     layoutSumPtr->truncVersion = root.truncVersion;
  622.     layoutSumPtr->numDataBlocks = 1;
  623.  
  624.     (*(int *) segPtr->summaryPtr) = 0;
  625.     segPtr->summaryPtr += sizeof(int);
  626.  
  627. }
  628.  
  629.  
  630. /*
  631.  *----------------------------------------------------------------------
  632.  *
  633.  * BuildInitialDescMap --
  634.  *
  635.  *    Build the initial descriptor structure for a file system.
  636.  *
  637.  * Results:
  638.  *    None.
  639.  *
  640.  * Side effects:
  641.  *    None.
  642.  *
  643.  *----------------------------------------------------------------------
  644.  */
  645.  
  646. void
  647. BuildInitialDescMap(descParamsPtr, segPtr, checkpointPtr)
  648.     LfsDescMapParams    *descParamsPtr; /* Parameters in super block to be 
  649.                      * filled in. */
  650.     SegMem        *segPtr;    /* Segment to add data blocks to. */
  651.     CheckPointMem    *checkpointPtr; /* Checkpoint info to be added. */
  652. {
  653.     LfsDescMapCheckPoint    *cp;
  654.     StableMem            *stableMemPtr;
  655.  
  656.     descParamsPtr->version = LFS_DESC_MAP_VERSION;
  657.     descParamsPtr->maxDesc = maxDesc;
  658.     if (maxDesc<0) {
  659.     fprintf(stderr,"Warning: maxDesc (%d) < 0\n", maxDesc);
  660.     }
  661.  
  662.     stableMemPtr = BuildStableMem(LFS_DESC_MAP_MOD, descMapBlockSize, 
  663.            sizeof(LfsDescMapEntry),  maxDesc,
  664.            &(descParamsPtr->stableMem));
  665.  
  666.     /*
  667.      * Reserve descriptors 0 and 1.
  668.      */
  669.     SetDescriptorMap(stableMemPtr, 0, 0, 0, 0);
  670.     SetDescriptorMap(stableMemPtr, 1, 0, 0, 0); 
  671.     SetDescriptorMap(stableMemPtr, FSDM_ROOT_FILE_NUMBER, 
  672.             root.descBlockAddress, 
  673.             root.truncVersion, root.accessTime);
  674.     SetDescriptorMap(stableMemPtr, FSDM_LOST_FOUND_FILE_NUMBER, 
  675.             root.descBlockAddress, 
  676.             root.truncVersion, root.accessTime);
  677.  
  678.     cp = (LfsDescMapCheckPoint *) checkpointPtr->memPtr;
  679.     cp->numAllocDesc = 4;
  680.     checkpointPtr->memPtr += sizeof(LfsDescMapCheckPoint);
  681.     LayoutStableMem(stableMemPtr, segPtr, checkpointPtr);
  682. }
  683.  
  684.  
  685. /*
  686.  *----------------------------------------------------------------------
  687.  *
  688.  * BuildInitialUsageArray --
  689.  *
  690.  *    Build the initial usage array structure for the file system.
  691.  *
  692.  * Results:
  693.  *    None.
  694.  *
  695.  * Side effects:
  696.  *    None.
  697.  *
  698.  *----------------------------------------------------------------------
  699.  */
  700.  
  701. void
  702. BuildInitialUsageArray(usagePtr, segPtr, checkpointPtr)
  703.     LfsSegUsageParams    *usagePtr;      /* Parameters in super block to be 
  704.                      * filled in. */
  705.     SegMem        *segPtr;    /* Segment to add data blocks to. */
  706.     CheckPointMem    *checkpointPtr; /* Checkpoint info to be added to. */
  707. {
  708.     LfsSegUsageCheckPoint    *cp;
  709.     LfsSegUsageEntry        entry;
  710.     int                i, numBlocks;
  711.     StableMem        *stableMemPtr;
  712.  
  713.     usagePtr->segmentSize = segmentSize;
  714.     usagePtr->numberSegments = numberSegments;
  715.     /*
  716.      * Set the minimum number of clean segments that we allow the system
  717.      * to get to before starting cleaning. We shouldn't let this 
  718.      * number get any smaller than the size of the data we clean.
  719.      * We make it two times this number to add a margin of safety.
  720.      * 
  721.      */
  722.     usagePtr->minNumClean = 2*(FS_BLOCK_SIZE * (maxCacheBlocksCleaned))
  723.                 /  segmentSize;
  724.     if (usagePtr->minNumClean < 10) {
  725.     usagePtr->minNumClean = 10;
  726.     }
  727.     numBlocks = numberSegments * (segmentSize/blockSize);
  728.     /*
  729.      * Set the minimum number of free blocks allowed. This should be
  730.      * based on the max disk space utilization required of the disk.
  731.      * For very small disk this number may be dominated by the minNumClean
  732.      * value.
  733.      */
  734.     usagePtr->minFreeBlocks = (int) (numBlocks - (numBlocks * maxUtilization));
  735.     if (usagePtr->minFreeBlocks < 
  736.         (usagePtr->minNumClean+10)*(segmentSize/blockSize)) {
  737.     usagePtr->minFreeBlocks = 
  738.         (usagePtr->minNumClean+10)*(segmentSize/blockSize);
  739.     }
  740.  
  741.     if (numBlocks < usagePtr->minFreeBlocks) {
  742.     fprintf(stderr,"Warning: numblocks < minFreeBlocks (%d vs %d)\n",
  743.         numBlocks, usagePtr->minFreeBlocks);
  744.     }
  745.  
  746.     usagePtr->wasteBlocks = (FS_BLOCK_SIZE/blockSize) + 2;
  747.  
  748.     /* 
  749.      * Number of segments to clean before stoping because there is
  750.      * until already clean. We clean enough to write back the
  751.      * entire file cache. 
  752.      */
  753.     usagePtr->numSegsToClean = 1+(maxNumCacheBlocks*FS_BLOCK_SIZE)/segmentSize;
  754.     if (usagePtr->numSegsToClean + usagePtr->minNumClean >= 
  755.         (int) (numberSegments*maxUtilization)) {
  756.     usagePtr->numSegsToClean = (int) (numberSegments*maxUtilization) - 
  757.                         usagePtr->minNumClean - 10;
  758.     if (usagePtr->numSegsToClean<=0) {
  759.         fprintf(stderr,"Warning: numSegsToClean = %d\n",
  760.             usagePtr->numSegsToClean);
  761.     }
  762.     }
  763.  
  764.  
  765.     stableMemPtr = BuildStableMem(LFS_SEG_USAGE_MOD, usageArrayBlockSize, 
  766.            sizeof(LfsSegUsageEntry),  numberSegments,
  767.            &(usagePtr->stableMem));
  768.  
  769.     /*
  770.      * Link all clean segments togther. 
  771.      */
  772.     entry.activeBytes = 0;
  773.     entry.flags = LFS_SEG_USAGE_DIRTY;
  774.     UpdateStableMem(stableMemPtr, 0, (char *) &entry);
  775.  
  776.     for (i = 1; i < numberSegments; i++) {
  777.     entry.activeBytes = i+1;
  778.     entry.flags = LFS_SEG_USAGE_CLEAN;
  779.     UpdateStableMem(stableMemPtr, i, (char *) &entry);
  780.     }
  781.     entry.activeBytes = NIL;
  782.     entry.flags = LFS_SEG_USAGE_CLEAN;
  783.     UpdateStableMem(stableMemPtr, numberSegments-1, (char *) &entry);
  784.  
  785.     cp = (LfsSegUsageCheckPoint *) checkpointPtr->memPtr;
  786.     cp->numClean = numberSegments-1;
  787.     cp->numDirty = 1;
  788.     cp->dirtyActiveBytes = (int) (segmentSize * segFullLevel);
  789.     cp->currentSegment = 0;
  790.     cp->currentBlockOffset = -1;
  791.     checkpointPtr->memPtr += sizeof(LfsSegUsageCheckPoint);
  792.     LayoutStableMem(stableMemPtr, segPtr, checkpointPtr);
  793.     cp->curSegActiveBytes = segPtr->activeBytes;
  794.     cp->previousSegment = -1;
  795.     cp->cleanSegList = 1;
  796.     cp->freeBlocks = numberSegments*(segmentSize/blockSize) - 
  797.              (segPtr->activeBytes + blockSize - 1)/blockSize;
  798. }
  799.  
  800. /*
  801.  *----------------------------------------------------------------------
  802.  *
  803.  * BuildStableMem --
  804.  *
  805.  *    Build the stable memory map.
  806.  *
  807.  * Results:
  808.  *    A StableMem structure that can be used to calls to UpdateStableMem
  809.  *    and LayoutStableMem.
  810.  *
  811.  * Side effects:
  812.  *    None.
  813.  *
  814.  *----------------------------------------------------------------------
  815.  */
  816.  
  817. static StableMem *
  818. BuildStableMem(memType, memBlockSize, entrySize, maxNumEntries, smemParamsPtr)
  819.     int     memType;    /* Type number of stable memory map. */
  820.     int     memBlockSize;    /* Block size of the memory. */
  821.     int     entrySize;    /* Size of each entry in bytes. */
  822.     int     maxNumEntries; /* Maximum number of entries supported. */
  823.     LfsStableMemParams *smemParamsPtr; /* Stable mem params to fill in. */
  824. {
  825.     StableMem            *stableMemPtr;
  826.  
  827.     /*
  828.      * Fill in the params for this map.
  829.      */
  830.     if (maxNumEntries<=0) {
  831.     fprintf(stderr,"Warning:maxNumEntries (%d) < 0\n", maxNumEntries);
  832.     }
  833.     if (entrySize<=0) {
  834.     fprintf(stderr,"Warning:entrySize (%d) < 0\n", entrySize);
  835.     }
  836.     smemParamsPtr->memType = memType;
  837.     smemParamsPtr->blockSize = memBlockSize;
  838.     smemParamsPtr->entrySize = entrySize;
  839.     smemParamsPtr->maxNumEntries = maxNumEntries;
  840.  
  841.     smemParamsPtr->entriesPerBlock = 
  842.         (memBlockSize - sizeof(LfsStableMemBlockHdr)) / entrySize;
  843.     smemParamsPtr->maxNumBlocks = BlockCount(maxNumEntries, 
  844.                     smemParamsPtr->entriesPerBlock);
  845.  
  846.     stableMemPtr = (StableMem *) calloc(1, sizeof(StableMem));
  847.     stableMemPtr->paramsPtr = smemParamsPtr;
  848.     stableMemPtr->blockPtrs = (char **) malloc(sizeof(char *) * 
  849.                         smemParamsPtr->maxNumBlocks);
  850.  
  851.     bzero((char *) stableMemPtr->blockPtrs, sizeof(char *) * 
  852.                         smemParamsPtr->maxNumBlocks);
  853.  
  854.     return stableMemPtr;
  855. }
  856.  
  857. /*
  858.  *----------------------------------------------------------------------
  859.  *
  860.  * UpdateStableMem --
  861.  *
  862.  *    Update an entry in a stable memory data structure.
  863.  *
  864.  * Results:
  865.  *    None.
  866.  *
  867.  * Side effects:
  868.  *    None.
  869.  *
  870.  *----------------------------------------------------------------------
  871.  */
  872. static void
  873. UpdateStableMem(stableMemPtr, entryNumber, entryPtr)
  874.     StableMem    *stableMemPtr;        /* Stable memory data to update. */
  875.     int        entryNumber;    /* Entry number to upate. */
  876.     char    *entryPtr;    /* New value for entry entryNumber. */
  877. {
  878.     int         blockNum, offset;
  879.     LfsStableMemBlockHdr *hdrPtr;
  880.  
  881.     if ((entryNumber < 0) || 
  882.     (entryNumber >= stableMemPtr->paramsPtr->maxNumEntries)) {
  883.     panic("Entry number out of range\n");
  884.     }
  885.  
  886.     blockNum = entryNumber / stableMemPtr->paramsPtr->entriesPerBlock;
  887.     offset = (entryNumber % stableMemPtr->paramsPtr->entriesPerBlock) * 
  888.         stableMemPtr->paramsPtr->entrySize + 
  889.                 sizeof(LfsStableMemBlockHdr);
  890.  
  891.     if (stableMemPtr->blockPtrs[blockNum] == (char *) NULL) {
  892.     stableMemPtr->blockPtrs[blockNum] = 
  893.                 calloc(1, stableMemPtr->paramsPtr->blockSize);
  894.     hdrPtr = (LfsStableMemBlockHdr *) stableMemPtr->blockPtrs[blockNum];
  895.     hdrPtr->magic = LFS_STABLE_MEM_BLOCK_MAGIC;
  896.     hdrPtr->memType = stableMemPtr->paramsPtr->memType;
  897.     hdrPtr->blockNum = blockNum;
  898.     }
  899.     bcopy(entryPtr, stableMemPtr->blockPtrs[blockNum] + offset, 
  900.       stableMemPtr->paramsPtr->entrySize);
  901.  
  902. }
  903.  
  904. /*
  905.  *----------------------------------------------------------------------
  906.  *
  907.  * LayoutStableMem --
  908.  *
  909.  *    Add to a segment the contents of a stable memory data structure.
  910.  *
  911.  * Results:
  912.  *    None.
  913.  *
  914.  * Side effects:
  915.  *    Data, summary, and checkpoint region added to.
  916.  *
  917.  *----------------------------------------------------------------------
  918.  */
  919.  
  920. static void
  921. LayoutStableMem(stableMemPtr, segPtr, checkpointPtr)
  922.     StableMem    *stableMemPtr;        /* Stable memory data to layout. */
  923.     SegMem        *segPtr;    /* Segment to add data blocks to. */
  924.     CheckPointMem    *checkpointPtr; /* Checkpoint info to be added to. */
  925. {
  926.     LfsStableMemCheckPoint    *cp;
  927.     int    block;
  928.  
  929.     cp = (LfsStableMemCheckPoint *) checkpointPtr->memPtr;
  930.     cp->numBlocks = 0;
  931.     checkpointPtr->memPtr += sizeof(LfsStableMemCheckPoint);
  932.     for (block = 0; block < stableMemPtr->paramsPtr->maxNumBlocks; block++) { 
  933.     if (stableMemPtr->blockPtrs[block]) {
  934.         segPtr->dataPtr -= stableMemPtr->paramsPtr->blockSize;
  935.         segPtr->activeBytes += stableMemPtr->paramsPtr->blockSize;
  936.         bcopy(stableMemPtr->blockPtrs[block],segPtr->dataPtr, 
  937.             stableMemPtr->paramsPtr->blockSize);
  938.         *((int *) (segPtr->summaryPtr)) = block;
  939.         segPtr->summaryPtr += sizeof(int);
  940.         cp->numBlocks++;
  941.         *((int *) (checkpointPtr->memPtr)) = 
  942.             GetDiskAddressOf(segPtr);
  943.         checkpointPtr->memPtr += sizeof(int);
  944.      } else {
  945.         *((int *) (checkpointPtr->memPtr)) = FSDM_NIL_INDEX;
  946.         checkpointPtr->memPtr += sizeof(int);
  947.      }
  948.     }
  949. }
  950.  
  951. /*
  952.  *----------------------------------------------------------------------
  953.  *
  954.  * MakeRootDir --
  955.  *
  956.  *    Make the initial root directory of a LFS file system..
  957.  *
  958.  * Results:
  959.  *    None.
  960.  *
  961.  * Side effects:
  962.  *    Data and summary blocks added to the segment.
  963.  *
  964.  *----------------------------------------------------------------------
  965.  */
  966. static void
  967. MakeRootDir(rootDescPtr, lostDescPtr, segPtr, rootPtr)
  968.     LfsFileDescriptor *rootDescPtr;  /* Root file descriptor to fill in. */
  969.     LfsFileDescriptor *lostDescPtr; /* Lost an found descriptor to fill 
  970.                        * in. */
  971.     SegMem        *segPtr;     /* Segment to add directory to. */
  972.     RootDir        *rootPtr;    /* Root directory info. */
  973. {
  974.     Fslcl_DirEntry *dirEntryPtr;
  975.     char *fileName, *dirPtr;
  976.     int length,  offset;
  977.  
  978.     FileDescInit(rootDescPtr, FSDM_ROOT_FILE_NUMBER, FS_DIRECTORY);
  979.     FileDescInit(lostDescPtr, FSDM_LOST_FOUND_FILE_NUMBER, FS_DIRECTORY);
  980.     segPtr->dataPtr -= FSLCL_DIR_BLOCK_SIZE;
  981.     segPtr->activeBytes += FSLCL_DIR_BLOCK_SIZE;
  982.     dirPtr = segPtr->dataPtr;
  983.     rootDescPtr->common.lastByte = FSLCL_DIR_BLOCK_SIZE-1;
  984.     rootDescPtr->common.direct[0] = GetDiskAddressOf(segPtr);
  985.     rootDescPtr->common.numKbytes = 1;
  986.     /*
  987.      * Place the data in the first filesystem block.
  988.      */
  989.     dirEntryPtr = (Fslcl_DirEntry *) dirPtr;
  990.  
  991.     fileName = ".";
  992.     length = strlen(fileName);
  993.     dirEntryPtr->fileNumber = FSDM_ROOT_FILE_NUMBER;
  994.     dirEntryPtr->recordLength = Fslcl_DirRecLength(length);
  995.     dirEntryPtr->nameLength = length;
  996.     strcpy(dirEntryPtr->fileName, fileName);
  997.     offset = dirEntryPtr->recordLength;
  998.     rootDescPtr->common.numLinks++;
  999.  
  1000.     dirEntryPtr = (Fslcl_DirEntry *)(dirPtr + offset);
  1001.     fileName = "..";
  1002.     length = strlen(fileName);
  1003.     dirEntryPtr->fileNumber = FSDM_ROOT_FILE_NUMBER;
  1004.     dirEntryPtr->recordLength = Fslcl_DirRecLength(length);
  1005.     dirEntryPtr->nameLength = length;
  1006.     strcpy(dirEntryPtr->fileName, fileName);
  1007.     offset += dirEntryPtr->recordLength;
  1008.     rootDescPtr->common.numLinks++;
  1009.  
  1010.     dirEntryPtr = (Fslcl_DirEntry *)(dirPtr + offset);
  1011.     fileName = "lost+found";
  1012.     length = strlen(fileName);
  1013.     dirEntryPtr->fileNumber = FSDM_LOST_FOUND_FILE_NUMBER;
  1014.     dirEntryPtr->recordLength = FSLCL_DIR_BLOCK_SIZE - offset;
  1015.     dirEntryPtr->nameLength = length;
  1016.     strcpy(dirEntryPtr->fileName, fileName);
  1017.     lostDescPtr->common.numLinks++;
  1018.  
  1019.  
  1020.  
  1021.     /*
  1022.      * Initialized and add to the segment the lost+found directory. 
  1023.      */
  1024.     segPtr->dataPtr -= FSLCL_DIR_BLOCK_SIZE;
  1025.     segPtr->activeBytes += FSLCL_DIR_BLOCK_SIZE;
  1026.     dirPtr = segPtr->dataPtr;
  1027.     lostDescPtr->common.lastByte = FSLCL_DIR_BLOCK_SIZE-1;
  1028.     lostDescPtr->common.direct[0] = GetDiskAddressOf(segPtr);
  1029.     lostDescPtr->common.numKbytes = 1;
  1030.     /*
  1031.      * Fill in the directory.
  1032.      */
  1033.     dirEntryPtr = (Fslcl_DirEntry *) dirPtr;
  1034.     fileName = ".";
  1035.     length = strlen(fileName);
  1036.     dirEntryPtr->fileNumber = FSDM_LOST_FOUND_FILE_NUMBER;
  1037.     dirEntryPtr->recordLength = Fslcl_DirRecLength(length);
  1038.     dirEntryPtr->nameLength = length;
  1039.     strcpy(dirEntryPtr->fileName, fileName);
  1040.     offset = dirEntryPtr->recordLength;
  1041.     lostDescPtr->common.numLinks++;
  1042.  
  1043.     dirEntryPtr = (Fslcl_DirEntry *)(dirPtr + offset);
  1044.     fileName = "..";
  1045.     length = strlen(fileName);
  1046.     dirEntryPtr->fileNumber = FSDM_ROOT_FILE_NUMBER;
  1047.     dirEntryPtr->recordLength = FSLCL_DIR_BLOCK_SIZE - offset;
  1048.     dirEntryPtr->nameLength = length;
  1049.     strcpy(dirEntryPtr->fileName, fileName);
  1050.     rootDescPtr->common.numLinks++;
  1051.  
  1052.     rootPtr->accessTime = rootDescPtr->common.accessTime;
  1053.     rootPtr->numBlocks = FSLCL_DIR_BLOCK_SIZE/blockSize;
  1054.     return;
  1055. }
  1056.  
  1057. /*
  1058.  *----------------------------------------------------------------------
  1059.  *
  1060.  * FileDescInit --
  1061.  *
  1062.  *    Initialized a LFS file descriptor.
  1063.  *
  1064.  * Results:
  1065.  *    None.
  1066.  *
  1067.  * Side effects:
  1068.  *    None.
  1069.  *
  1070.  *----------------------------------------------------------------------
  1071.  */
  1072.  
  1073. static void
  1074. FileDescInit(fileDescPtr, fileNumber, fileType)
  1075.     LfsFileDescriptor *fileDescPtr;     /* File descriptor to fill in. */
  1076.     int              fileNumber;    /* File number of descriptor. */
  1077.     int              fileType;        /* File type of the desc. */
  1078. {
  1079.     int  timeVal, index;
  1080.  
  1081.     fileDescPtr->fileNumber = fileNumber;
  1082.     fileDescPtr->common.magic = FSDM_FD_MAGIC;
  1083.     fileDescPtr->common.flags = FSDM_FD_ALLOC;
  1084.     fileDescPtr->common.fileType = fileType;
  1085.     fileDescPtr->common.permissions = 0755;
  1086.     fileDescPtr->common.uid = 0;
  1087.     fileDescPtr->common.gid = 0;
  1088.     fileDescPtr->common.lastByte = -1;
  1089.     fileDescPtr->common.firstByte = -1;
  1090.     fileDescPtr->common.numLinks = 0;
  1091.     /*
  1092.      * Can't know device information because that depends on
  1093.      * the way the system is configured.
  1094.      */
  1095.     fileDescPtr->common.devServerID = -1;
  1096.     fileDescPtr->common.devType = -1;
  1097.     fileDescPtr->common.devUnit = -1;
  1098.  
  1099.     /*
  1100.      * Set the time stamps.  This assumes that universal time, not local
  1101.      * time, is used for time stamps.
  1102.      */
  1103.     timeVal = time(0);
  1104.     fileDescPtr->common.createTime = timeVal;
  1105.     fileDescPtr->common.accessTime = timeVal;
  1106.     fileDescPtr->common.descModifyTime = timeVal;
  1107.     fileDescPtr->common.dataModifyTime = timeVal;
  1108.  
  1109.     /*
  1110.      * Initialize map to NILs.
  1111.      */
  1112.     for (index = 0; index < FSDM_NUM_DIRECT_BLOCKS ; index++) {
  1113.     fileDescPtr->common.direct[index] = FSDM_NIL_INDEX;
  1114.     }
  1115.     for (index = 0; index < FSDM_NUM_INDIRECT_BLOCKS ; index++) {
  1116.     fileDescPtr->common.indirect[index] = FSDM_NIL_INDEX;
  1117.     }
  1118.     fileDescPtr->common.numKbytes = 0;
  1119.     fileDescPtr->common.version = 1;
  1120. }
  1121.  
  1122. /*
  1123.  *----------------------------------------------------------------------
  1124.  *
  1125.  * SetDescriptorMap --
  1126.  *
  1127.  *    Set an entry in the descriptor map of the file system. 
  1128.  *
  1129.  * Results:
  1130.  *    None.
  1131.  *
  1132.  * Side effects:
  1133.  *    None.
  1134.  *
  1135.  *----------------------------------------------------------------------
  1136.  */
  1137.  
  1138. static void
  1139. SetDescriptorMap(stableMemPtr, fileNumber, diskAddress, truncVersion, 
  1140.             accessTime)
  1141.     StableMem    *stableMemPtr;   /* Stable memory of descriptor map. */
  1142.     int    fileNumber;         /* File number to set. */
  1143.     unsigned int diskAddress;    /* Disk address of file number. */
  1144.     int truncVersion;         /* Truncate version number of file. */
  1145.     int    accessTime;         /* Time of last file access. */
  1146. {
  1147.     LfsDescMapEntry entry;
  1148.  
  1149.     entry.blockAddress = diskAddress;
  1150.     entry.truncVersion = truncVersion;
  1151.     entry.flags = LFS_DESC_MAP_ALLOCED;
  1152.     entry.accessTime = accessTime;
  1153.     UpdateStableMem(stableMemPtr, fileNumber, (char *) &entry);
  1154. }
  1155.  
  1156. /*
  1157.  *----------------------------------------------------------------------
  1158.  *
  1159.  * GetDiskAddressOf --
  1160.  *
  1161.  *    Return the disk address of the current data pointer of the segment.
  1162.  *
  1163.  * Results:
  1164.  *    The disk address of last data block allocated.
  1165.  *
  1166.  * Side effects:
  1167.  *    None.
  1168.  *
  1169.  *----------------------------------------------------------------------
  1170.  */
  1171. static unsigned int 
  1172. GetDiskAddressOf(segPtr)
  1173.     SegMem    *segPtr;    /* Return the disk address of the current
  1174.                  * dataPtr. */
  1175. {
  1176.     int blockOffset;
  1177.     blockOffset = (segPtr->dataPtr - segPtr->startPtr) / blockSize;
  1178.     return segPtr->diskAddress + blockOffset;
  1179. }
  1180.  
  1181. /*
  1182.  *----------------------------------------------------------------------
  1183.  *
  1184.  * WriteDisk --
  1185.  *
  1186.  *    Write the the sepcified buffer to disk.
  1187.  *
  1188.  * Results:
  1189.  *    None.
  1190.  *
  1191.  * Side effects:
  1192.  *    This disk gets written or the program exits.
  1193.  *
  1194.  *----------------------------------------------------------------------
  1195.  */
  1196.  
  1197. static void
  1198. WriteDisk(diskFd, blockOffset, bufferPtr, bufferSize)
  1199.     int    diskFd;        /* Open file descriptor of disk. */
  1200.     int    blockOffset;    /* Block offset into disk to write. */
  1201.     char *bufferPtr;    /* Buffer to write. */
  1202.     int     bufferSize;    /* Number of bytes to write. */
  1203. {
  1204.     int    numBytes, status;
  1205.  
  1206.     numBytes = BlockCount(bufferSize, blockSize) * blockSize;
  1207.  
  1208.     status = lseek(diskFd, blockOffset*blockSize, L_SET);
  1209.     if (status < 0) {
  1210.     fprintf(stderr,"Writing device: ");
  1211.     perror("lseek");
  1212.     exit(1);
  1213.     }
  1214.     status = write(diskFd, bufferPtr, numBytes);
  1215.     if (status != numBytes) {
  1216.     if (status < 0) {
  1217.         fprintf(stderr,"Writing device: ");
  1218.         perror("write");
  1219.         exit(1);
  1220.     }
  1221.     fprintf(stderr,"Short write on device %d != %d, offset %d\n", 
  1222.         status, numBytes, blockOffset);
  1223.     panic("Goodbye");
  1224.     exit(1);
  1225.     }
  1226.  
  1227. }
  1228.  
  1229. /*
  1230.  *----------------------------------------------------------------------
  1231.  *
  1232.  * IsPowerOfTwo --
  1233.  *
  1234.  *    Check to see if the integer is a postive power of two.
  1235.  *
  1236.  * Results:
  1237.  *    TRUE if the argument is a power of two. FALSE otherwise.
  1238.  *
  1239.  * Side effects:
  1240.  *    None.
  1241.  *
  1242.  *----------------------------------------------------------------------
  1243.  */
  1244.  
  1245. static Boolean
  1246. IsPowerOfTwo(ival)
  1247.     int     ival;    /* Value to check. */
  1248. {
  1249.     if (ival <= 0) {
  1250.     return FALSE;
  1251.     }
  1252.     while (!(ival & 1)) {
  1253.     ival >>= 1;
  1254.     }
  1255.     return ((ival >> 1) == 0);
  1256. }
  1257.  
  1258. /*
  1259.  *----------------------------------------------------------------------
  1260.  *
  1261.  * IsMultipleOf --
  1262.  *
  1263.  *    Check to see if one integer is a multiple of another..
  1264.  *
  1265.  * Results:
  1266.  *    TRUE if they are multiples. FALSE otherwise.
  1267.  *
  1268.  * Side effects:
  1269.  *    None.
  1270.  *
  1271.  *----------------------------------------------------------------------
  1272.  */
  1273.  
  1274. static Boolean
  1275. IsMultipleOf(imultiple, ival)
  1276.     int    imultiple;    /* Value to check against ival. */
  1277.     int ival;        /* Base value. */
  1278. {
  1279.     int    itemp;
  1280.  
  1281.     itemp = imultiple/ival;
  1282.  
  1283.     return (itemp*ival == imultiple);
  1284. }
  1285.  
  1286.  
  1287. /*
  1288.  *----------------------------------------------------------------------
  1289.  *
  1290.  * BlockCount  --
  1291.  *
  1292.  *    Return how many blocks of a specified size it will take to 
  1293.  *    the specified object.
  1294.  *
  1295.  * Results:
  1296.  *    Number of blocks.
  1297.  *
  1298.  * Side effects:
  1299.  *    None.
  1300.  *
  1301.  *----------------------------------------------------------------------
  1302.  */
  1303.  
  1304. static int
  1305. BlockCount(objectSize, blockSize)
  1306.     int    objectSize;    /* Size of object in bytes. */
  1307.     int blockSize;    /* Block size in bytes. */
  1308. {
  1309.  
  1310.     return (objectSize + (blockSize-1))/blockSize;
  1311. }
  1312.  
  1313. #include <disk.h>
  1314.  
  1315. /*
  1316.  *----------------------------------------------------------------------
  1317.  *
  1318.  * EraseOldFileSystem --
  1319.  *
  1320.  *    Erase the old OFS file system from the disk so that the kernel
  1321.  *    attach code wont file it.
  1322.  *
  1323.  * Results:
  1324.  *    None.
  1325.  *
  1326.  * Side effects:
  1327.  *    None.
  1328.  *
  1329.  *----------------------------------------------------------------------
  1330.  */
  1331.  
  1332. static void
  1333. EraseOldFileSystem(diskFd)
  1334.     int    diskFd;    /* Open file descriptor of disk. */
  1335. {
  1336.     Disk_Label  *labelPtr;
  1337.     int        status, i;
  1338.     static    char bufferOfZeros[DEV_BYTES_PER_SECTOR];
  1339.  
  1340.     labelPtr = Disk_ReadLabel(diskFd);
  1341.     if (labelPtr == (Disk_Label *) NULL) {
  1342.     return;
  1343.     }
  1344.     if (labelPtr->summarySector > 0) {
  1345.     status = lseek(diskFd, 
  1346.             DEV_BYTES_PER_SECTOR*labelPtr->summarySector, L_SET);
  1347.     if (status > 0) {
  1348.         status = write(diskFd, bufferOfZeros, DEV_BYTES_PER_SECTOR);
  1349.     }
  1350.     if (status < 0) {
  1351.         fprintf(stderr,"Erasing old file system: ");
  1352.         perror("write");
  1353.     }
  1354.     }
  1355.     if (labelPtr->domainSector > 0) {
  1356.     for (i = 0; i < labelPtr->numDomainSectors; i++) {
  1357.         status = lseek(diskFd, 
  1358.             DEV_BYTES_PER_SECTOR*(labelPtr->domainSector+i), L_SET);
  1359.         if (status > 0) {
  1360.         status = write(diskFd, bufferOfZeros, DEV_BYTES_PER_SECTOR);
  1361.         }
  1362.         if (status < 0) {
  1363.         fprintf(stderr,"Erasing old file system: ");
  1364.         perror("write");
  1365.         }
  1366.      }
  1367.  
  1368.     }
  1369. }
  1370.  
  1371. /*
  1372.  *----------------------------------------------------------------------
  1373.  *
  1374.  * ComputeDiskSize --
  1375.  *
  1376.  *    Compute the size of the disk by reading it from the disk label.
  1377.  *
  1378.  * Results:
  1379.  *    -1 if can't compute size.  The size.
  1380.  *
  1381.  * Side effects:
  1382.  *    None.
  1383.  *
  1384.  *----------------------------------------------------------------------
  1385.  */
  1386. static int
  1387. ComputeDiskSize(diskFd)
  1388.     int    diskFd;    /* Open file descriptor of disk. */
  1389. {
  1390.     struct stat sbuf;
  1391.     Disk_Label  *labelPtr;
  1392.     int        partition, sizeInSectors;
  1393.  
  1394.     labelPtr = Disk_ReadLabel(diskFd);
  1395.     if (labelPtr == (Disk_Label *) NULL) {
  1396.     printf("Couldn't read label\n");
  1397.     return -1;
  1398.     }
  1399.     if (fstat(diskFd, &sbuf) < 0) {
  1400.     printf("Couldn't stat disk\n");
  1401.     return -1;
  1402.     }
  1403. #ifdef ds3100
  1404.     /*
  1405.      * Handle some bogusness in the ds3100 port.
  1406.      */
  1407.     partition = unix_minor(sbuf.st_rdev) & 0x7;
  1408. #else
  1409.     partition = minor(sbuf.st_rdev) & 0x7;
  1410. #endif
  1411.     sizeInSectors = labelPtr->partitions[partition].numCylinders * 
  1412.             labelPtr->numHeads * labelPtr->numSectors;
  1413.     if (sizeInSectors <= 0) {
  1414.     printf("label gives bad size: %d cyl, %d head, %d sectors\n",
  1415.         labelPtr->partitions[partition].numCylinders,
  1416.         labelPtr->numHeads, labelPtr->numSectors);
  1417.     sizeInSectors = -1;
  1418.     }
  1419.     return sizeInSectors;
  1420. }
  1421.